namespace Profit.ViewModels
{
    using System;
    using System.Collections.Generic;
    using System.Collections.ObjectModel;
    using System.ComponentModel;
    using System.Diagnostics;
    using System.IO;
    using System.Linq;
    using System.Reflection;
    using System.Text;
    using System.Threading.Tasks;
    using System.Windows;
    using System.Windows.Input;
    using Core;
    using Core.Contracts.Interfaces;
    using Diagnostic;
    using Resources;
    using Services;
    using Views;
    using Views.Interfaces;
    using Properties;


    public sealed class MainViewModel : ViewModelBase<IMainView>
    {
        private const string VIEW_TITLE_FORMAT = "{0}{1}";
        private const string NEW_VERSION_URL = "http://profit.codeplex.com/project/feeds/rss?ProjectRSSFeed=codeplex://release/profit";

        private readonly UpdateChecker _updateChecker;
        private readonly ClipboardExplorer _clipboard;

        private IAgent _selectedAgent;
        private IFitting _selectedFitting;

        private ICommand _clearModules = null;
        private ICommand _newFittingCommand = null;
        private ICommand _addModuleCommand = null;
        private ICommand _removeModuleCommand = null;
        private ICommand _showAgentDetailsCommand = null;
        private ICommand _selectAgentCommand = null;
        private ICommand _selectFittingCommand = null;
        private ICommand _deleteFittingCommand = null;
        private ICommand _renameFittingCommand = null;
        private ICommand _saveFittingCommand = null;
        private ICommand _exportFittingCommand = null;
        private ICommand _exitCommand = null;
        private ICommand _settingsCommand = null;
        private ICommand _aboutCommand = null;
        private ICommand _newAgentCommand = null;
        private ICommand _deleteAgentCommand = null;
        private ICommand _fittingsListCommand = null;

        private List<IView> _children;

        /// <summary>
        /// Creates a new instance
        /// </summary>
        /// <param name="view">The IView instance associated</param>
        public MainViewModel(IMainView view)
            : base(view)
        {
            SetViewTitle();

            view.Closing += OnMainViewClosing;

            _updateChecker = new UpdateChecker(NEW_VERSION_URL);
            _updateChecker.NewVersionAvailable += (s, e) => view.Dispatcher.Invoke(
                new ActionDelegate<NewVersionAvailableEventArgs>(ShowDownloadNewVersionConfirmation), e);

            if (Settings.Default.CheckNewVersionOnStartup)
                _updateChecker.SearchNewVersion(Assembly.GetEntryAssembly().GetName().Version);

            // Starts a clipboard monitoring for stored fitting
            _clipboard = new ClipboardExplorer(view.Dispatcher, TimeSpan.FromSeconds(5));
            _clipboard.FittingStored += OnFittingDiscovered;
            _clipboard.Start();
        }

        /// <summary>
        /// Obtains the application trace events
        /// </summary>
        public ObservableCollection<TraceEventArgs> Events
        {
            get { return App.Events; }
        }
        /// <summary>
        /// Obtains the agents collection
        /// </summary>
        public ObservableCollection<IAgent> Agents
        {
            get { return Repository.Agents; }
        }
        /// <summary>
        /// Determines if the agent collection contains any agent
        /// </summary>
        public bool HasAgents
        {
            get { return Repository.Agents.Any(); }
        }
        /// <summary>
        /// Obtains the robot fittings collection
        /// </summary>
        public ObservableCollection<IFitting> Fittings
        {
            get { return Repository.Fittings; }
        }
        /// <summary>
        /// Deterimnes if the robot fittings collection contains any robot
        /// </summary>
        public bool HasFittings
        {
            get { return Repository.Fittings.Any(); }
        }
        /// <summary>
        /// Obtains or defines the selected agent
        /// </summary>
        public IAgent SelectedAgent
        {
            get { return _selectedAgent; }
            set
            {
                _selectedAgent = value;
                NotifyPropertyChange(() => SelectedAgent, () => HasSelectedAgent);

                if (SelectedRobot != null)
                    SelectedRobot.Pilot = _selectedAgent;
            }
        }
        /// <summary>
        /// Determines if there is a selected agent
        /// </summary>
        public bool HasSelectedAgent
        {
            get { return SelectedAgent != null; }
        }
        /// <summary>
        /// Obtains or defines the selected fitting
        /// </summary>
        public IFitting SelectedFitting
        {
            get { return _selectedFitting; }
            set
            {
                _selectedFitting = value;
                NotifyPropertyChange(() => HasSelectedFitting, () => SelectedFitting);

                if (_selectedFitting != null && _selectedFitting.Robot != null)
                    _selectedFitting.Robot.Pilot = SelectedAgent;

                if (SelectedAgent != null)
                    NotifyPropertyChange(() => SelectedRobot); // Refresh robot stats view
            }
        }
        /// <summary>
        /// Determines if the selected fitting is not null and dirty
        /// </summary>
        public bool IsFittingDirty
        {
            get { return SelectedFitting != null && SelectedFitting.IsDirty; }
        }
        /// <summary>
        /// Obtains or defines the selected robot
        /// </summary>
        public IRobot SelectedRobot
        {
            get { return SelectedFitting == null ? null : SelectedFitting.Robot; }
            set
            {
                if (SelectedFitting == null && value == null) return;

                if (SelectedFitting == null)
                    SelectedFitting = new Fitting(value.Name);

                SelectedFitting.Robot = value;
                NotifyPropertyChange(() => SelectedRobot);

                if (SelectedFitting.Robot != null)
                    SelectedFitting.Robot.Pilot = SelectedAgent;
            }
        }
        /// <summary>
        /// 
        /// </summary>
        public bool HasSelectedRobot
        {
            get { return SelectedRobot != null; }
        }
        /// <summary>
        /// 
        /// </summary>
        public bool HasSelectedFitting
        {
            get { return SelectedFitting != null; }
        }
        /// <summary>
        /// 
        /// </summary>
        public ICommand ExitCommand
        {
            get { return _exitCommand ?? (_exitCommand = new BindableCommand<object>(OnExitCommandHandler)); }
        }
        /// <summary>
        /// 
        /// </summary>
        public ICommand ClearModulesCommand
        {
            get { return _clearModules ?? (_clearModules = new BindableCommand<object>(ClearModulesCommandHandler)); }
        }
        /// <summary>
        /// 
        /// </summary>
        public ICommand NewFittingCommand
        {
            get { return _newFittingCommand ?? (_newFittingCommand = new BindableCommand<string>(NewFittingCommandHandler)); }
        }
        /// <summary>
        /// 
        /// </summary>
        public ICommand ShowAgentDetailsCommand
        {
            get { return _showAgentDetailsCommand ?? (_showAgentDetailsCommand = new BindableCommand<IAgent>(ShowAgentDetailsCommandHandler)); }
        }
        /// <summary>
        /// 
        /// </summary>
        public ICommand NewAgentCommand
        {
            get { return _newAgentCommand ?? (_newAgentCommand = new BindableCommand<object>(NewAgentCommandHandler)); }
        }
        /// <summary>
        /// 
        /// </summary>
        public ICommand DeleteAgentCommand
        {
            get { return _deleteAgentCommand ?? (_deleteAgentCommand = new BindableCommand<IAgent>(DeleteAgentCommandHandler)); }
        }
        /// <summary>
        /// 
        /// </summary>
        public ICommand AddModuleCommand
        {
            get { return _addModuleCommand ?? (_addModuleCommand = new BindableCommand<IModule>(AddModuleCommandHandler)); }
        }
        /// <summary>
        /// 
        /// </summary>
        public ICommand RemoveModuleCommand
        {
            get { return _removeModuleCommand ?? (_removeModuleCommand = new BindableCommand<IModule>(RemoveModuleCommandHandler)); }
        }
        /// <summary>
        /// 
        /// </summary>
        public ICommand SelectAgentCommand
        {
            get { return _selectAgentCommand ?? (_selectAgentCommand = new BindableCommand<IAgent>(SelectAgentCommandHandler)); }
        }
        /// <summary>
        /// 
        /// </summary>
        public ICommand SelectFittingCommand
        {
            get { return _selectFittingCommand ?? (_selectFittingCommand = new BindableCommand<IFitting>(SelectFittingCommandHandler)); }
        }
        /// <summary>
        /// 
        /// </summary>
        public ICommand RenameFittingCommand
        {
            get { return _renameFittingCommand ?? (_renameFittingCommand = new BindableCommand<IFitting>(RenameFittingCommandHandler)); }
        }
        /// <summary>
        /// 
        /// </summary>
        public ICommand DeleteFittingCommand
        {
            get { return _deleteFittingCommand ?? (_deleteFittingCommand = new BindableCommand<IFitting>(DeleteFittingCommandHandler)); }
        }
        /// <summary>
        /// 
        /// </summary>
        public ICommand SaveFittingCommand
        {
            get { return _saveFittingCommand ?? (_saveFittingCommand = new BindableCommand<IFitting>(SaveFittingCommandHandler)); }
        }
        /// <summary>
        /// Obtains the ExportFittingCommand
        /// </summary>
        public ICommand ExportFittingCommand
        {
            get { return _exportFittingCommand ?? (_exportFittingCommand = new BindableCommand<IFitting>(ExportFittingCommandHandler)); }
        }
        /// <summary>
        /// 
        /// </summary>
        public ICommand SettingsCommand
        {
            get { return _settingsCommand ?? (_settingsCommand = new BindableCommand<object>(SettingsCommandHandler)); }
        }
        /// <summary>
        /// 
        /// </summary>
        public ICommand FittingsListCommand
        {
            get { return _fittingsListCommand ?? (_fittingsListCommand = new BindableCommand<object>(FittingsListCommandHandler)); }
        }
        /// <summary>
        /// 
        /// </summary>
        public ICommand AboutCommand
        {
            get { return _aboutCommand ?? (_aboutCommand = new BindableCommand<object>(AboutCommandHandler)); }
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="state"></param>
        private void FittingsListCommandHandler(object state)
        {
            var vm = new FittingsViewModel(new FittingsView(), Fittings, DeleteFittingCommand, ExportFittingCommand);
            vm.PropertyChanged += (s, e) =>
            {
                if (e.PropertyName == "SelectedFitting" && vm.SelectedFitting != null)
                {
                    SelectedFitting = vm.SelectedFitting;
                    vm.View.Close();
                }
            };

            vm.View.ShowDialog(View);
        }
        /// <summary>
        /// Defines the view title
        /// </summary>
        private void SetViewTitle()
        {
            View.Title = string.Format(
                VIEW_TITLE_FORMAT,
                Messages.view_title_main,
                " - Version: " + Assembly.GetEntryAssembly().GetName().Version);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="agent"></param>
        private void ShowAgentDetailsCommandHandler(IAgent agent)
        {
            if (agent == null)
            {
                App.Trace.TraceEvent(TraceEventType.Warning, 0, "No agent selected");
                return;
            }

            if (_children == null)
                _children = new List<IView>();

            // Checking if there isn't a view already open for that agent
            var view = _children.Where(v => v.GetType() == typeof(AgentView) &&
                Equals(((AgentViewModel)v.DataContext).SelectedAgent, agent)).FirstOrDefault();
            if (view != null)
            {
                // a view is already open, bringing it to front
                view.Activate();
                return;
            }

            var vm = new AgentViewModel(new AgentView(), agent);
            vm.View.Show();

            vm.View.Closing += OnChildViewClosing;
            _children.Add(vm.View);

        }
        /// <summary>
        /// SelectAgentCommand ICommand handler
        /// </summary>
        /// <param name="agent"></param>
        private void SelectAgentCommandHandler(IAgent agent)
        {
            if (agent == null) return;
            SelectedAgent = agent;
        }
        /// <summary>
        /// NewAgentCommand ICommand handler
        /// </summary>
        /// <param name="state">null</param>
        private void NewAgentCommandHandler(object state)
        {
            var newAgent = Agent.CreateNew(Messages.label_new_agent_name);
            var vm = new AgentViewModel(new AgentView(), newAgent);
            var result = vm.View.ShowDialog(View);
            if (result.HasValue && result.Value)
            {
                Repository.Agents.Add(newAgent);
                Repository.SaveAgents();

                if (SelectedAgent == null)
                    SelectedAgent = newAgent;
            }
        }
        /// <summary>
        /// DeleteAgentCommand ICommand handler
        /// </summary>
        /// <param name="agent"></param>
        private void DeleteAgentCommandHandler(IAgent agent)
        {
            if (agent == null)
            {
                App.Trace.TraceEvent(TraceEventType.Warning, 0, "No agent selected");
                return;
            }
            var vm = new ConfirmationViewModel(new ConfirmationView(), string.Format(Messages.message_confirmation_delete_agent, agent.Name)) { ButtonOkContent = Messages.label_delete, ButtonCancelContent = Messages.label_cancel };
            var result = vm.View.ShowDialog(this.View);
            if (result.HasValue && result.Value)
            {
                Agents.Remove(agent);
                if (SelectedAgent == agent)
                {
                    SelectedAgent = null;
                    if (HasAgents)
                        SelectedAgent = Agents[0];
                }

                Repository.SaveAgents();
            }
        }
        /// <summary>
        /// ClearModules ICommand handler
        /// </summary>
        /// <param name="value">null</param>
        private void ClearModulesCommandHandler(object value)
        {
            if (SelectedRobot == null)
            {
                App.Trace.TraceEvent(TraceEventType.Warning, 0, "No robot selected");
                return;
            }
            SelectedRobot.ClearModules();
            SelectedFitting.IsDirty = true;
        }
        /// <summary>
        /// NewFittingCommand ICommand handler
        /// </summary>
        /// <param name="robot">Robot name</param>
        private void NewFittingCommandHandler(string robot)
        {
            if (String.IsNullOrEmpty(robot)) return;
            if (SelectedAgent == null)
            {
                App.Trace.TraceEvent(TraceEventType.Warning, 0, "No agent selected");
                return;
            }

            var selectedBot = Repository.Default.LoadByName<IRobot>(robot);
            if (selectedBot == null)
            {
                App.Trace.TraceEvent(TraceEventType.Warning, 0, "No robot found");
                return;
            }

            CheckPendingFittingChanges();

            string fittingName = selectedBot.Name;

            if (Repository.Fittings.Exists(fittingName))
            {
                int count = 1;
                fittingName = string.Format("{0} - {1}", selectedBot.Name, count);
                while (Repository.Fittings.Exists(fittingName))
                {
                    fittingName = string.Format("{0} - {1}", selectedBot.Name, count++);
                }
            }

            SelectedFitting = new Fitting(fittingName);

            SelectedRobot = selectedBot;
            SelectedRobot.Pilot = SelectedAgent;

            Repository.Fittings.Add(SelectedFitting);
        }
        /// <summary>
        /// RemoveModuleCommand ICommand Handler
        /// </summary>
        /// <param name="module">An IModule instance to remove</param>
        private void RemoveModuleCommandHandler(IModule module)
        {
            if (SelectedRobot == null)
            {
                App.Trace.TraceEvent(TraceEventType.Warning, 0, "No robot selected");
                return;
            }

            if (module == null)
            {
                App.Trace.TraceEvent(TraceEventType.Warning, 0, "No module found");
                return;
            }
            SelectedRobot.RemoveModule(module, true);
            SelectedFitting.IsDirty = true;
        }
        /// <summary>
        /// AddModuleCommand ICommand Handler
        /// </summary>
        /// <param name="module">The module to add</param>
        private void AddModuleCommandHandler(IModule module)
        {
            if (SelectedRobot == null)
            {
                App.Trace.TraceEvent(TraceEventType.Warning, 0, "No robot selected");
                return;
            }

            if (module == null)
            {
                App.Trace.TraceEvent(TraceEventType.Warning, 0, "No module found");
                return;
            }

            var newMod = (IModule)module.Clone();

            if (newMod.CanHaveAmmunitions)
                newMod.LoadUsableAmmunitions();

            if (SelectedRobot.AddModule(newMod, true))
                SelectedFitting.IsDirty = true;
        }
        /// <summary>
        /// SelectFittingCommand ICommand handler
        /// </summary>
        /// <param name="fitting"></param>
        private void SelectFittingCommandHandler(IFitting fitting)
        {
            if (fitting == null)
            {
                App.Trace.TraceEvent(TraceEventType.Warning, 0, "No fitting selected");
                return;
            }

            CheckPendingFittingChanges();

            SelectedFitting = fitting;
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="fitting"></param>
        private void DeleteFittingCommandHandler(IFitting fitting)
        {
            if (fitting == null)
            {
                App.Trace.TraceEvent(TraceEventType.Warning, 0, "No fitting selected");
                return;
            }

            var vm = new ConfirmationViewModel(new ConfirmationView(), string.Format(Messages.message_confirmation_delete_fitting, fitting.Name)) { ButtonOkContent = Messages.label_delete, ButtonCancelContent = Messages.label_cancel };
            var result = vm.View.ShowDialog(this.View);
            if (result.HasValue && result.Value)
            {
                Fittings.Remove(fitting);
                if (SelectedFitting == fitting)
                    SelectedFitting = null;

                Repository.SaveFittings(true);
            }
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="fitting"></param>
        private void RenameFittingCommandHandler(IFitting fitting)
        {
            if (fitting == null)
            {
                App.Trace.TraceEvent(TraceEventType.Warning, 0, "No fitting selected");
                return;
            }

            var vm = new TextViewModel(new TextView()) { Label = Messages.label_name, Text = fitting.Name };
            var result = vm.View.ShowDialog(View);
            if (result.HasValue && result.Value)
            {
                if (Repository.Fittings.Exists(vm.Text))
                {
                    var conf = new ConfirmationViewModel(new ConfirmationView(), string.Format(Messages.message_fitting_name_already_exists, vm.Text)) { ButtonOkContent = Messages.label_ok, ShowButtonCancel = false, Title = Messages.label_error };
                    conf.View.ShowDialog(this.View);
                }
                else fitting.Name = vm.Text;
            }
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="fitting"></param>
        private static void SaveFittingCommandHandler(IFitting fitting)
        {
            if (fitting == null)
            {
                App.Trace.TraceEvent(TraceEventType.Warning, 0, "No fitting selected");
                return;
            }

            if (!Repository.Fittings.Contains(fitting))
                Repository.Fittings.Add(fitting);

            Repository.SaveFittings(true);
        }
        /// <summary>
        /// ExportFittingCommand ICommand handler
        /// </summary>
        /// <param name="fitting">An IFitting instance</param>
        private void ExportFittingCommandHandler(IFitting fitting)
        {
            if (fitting == null)
            {
                App.Trace.TraceEvent(TraceEventType.Warning, 0, "No fitting selected");
                return;
            }

            var text = new TextFittingExporter().Export(fitting);
            if (string.IsNullOrEmpty(text)) return;

            _clipboard.IgnoreFitting(fitting.Name);

            bool success = false;
            try
            {
                Clipboard.SetText(text);
                success = true;

                App.Trace.TraceInformation("Fitting {0} exported to clipboard", fitting.Name);
            }
            catch (Exception exp)
            {
                App.Trace.TraceEvent(TraceEventType.Error, 0, "An exception of type \"{0}\" occured while attempting to copy the fitting \"{1}\" to the clipboard. Details: {2}", exp.GetType(), fitting.Name, exp.Message);
            }

            
            if (!success)
            {
                // Failed to copy data to clipboard
                // Create a temp file and paste content into the open it
                try
                {
                    var tmpfile = Path.GetTempPath() + fitting.Name + ".txt";
                    File.Delete(tmpfile);
                    using (var writer = new StreamWriter(tmpfile, false, Encoding.UTF8))
                        writer.Write(text);

                    Process.Start(tmpfile);
                }
                catch (Exception exp)
                {
                    App.Trace.TraceEvent(TraceEventType.Error, 0, "An exception of type \"{0}\" occured while attempting to copy the fitting \"{1}\" to a temporary file. Details: {2}", exp.GetType(), fitting.Name, exp.Message);
                }
            }
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="state"></param>
        private void OnExitCommandHandler(object state)
        {
            _clipboard.FittingStored -= OnFittingDiscovered;
            _clipboard.Stop();
            View.Close();
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="state"></param>
        private void SettingsCommandHandler(object state)
        {
            var vm = new SettingsViewModel(new SettingsView());
            var result = vm.View.ShowDialog(this.View);
            if (result.HasValue && result.Value)
            {
                // Checking if we have write/delete access to directories defined in settings
                // if not, restore value to default
                if (!IsLocalApplicationPath(Settings.Default.PathLog) && 
                    !CanWriteInDirectory(Settings.Default.PathLog))
                {
                    Trace.TraceError("Cannot write a file in \"{0}\". Restoring default value.", Path.GetFullPath( Settings.Default.PathLog));
                    Settings.Default.PathLog = ".";
                }
                if (!IsLocalApplicationPath(Settings.Default.PathAgents) && 
                    !CanWriteInDirectory(Settings.Default.PathAgents))
                {
                    Trace.TraceError("Cannot write a file in \"{0}\". Restoring default value.", Path.GetFullPath(Settings.Default.PathAgents));
                    Settings.Default.PathAgents = ".";
                }
                
                if (!IsLocalApplicationPath(Settings.Default.PathFittings) && 
                    !CanWriteInDirectory(Settings.Default.PathFittings))
                {
                    Trace.TraceError("Cannot write a file in \"{0}\". Restoring default value.", Path.GetFullPath(Settings.Default.PathFittings));
                    Settings.Default.PathFittings = ".";
                }

                Settings.Default.Save();
            }
            else
                Settings.Default.Reload();
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="state"></param>
        private void AboutCommandHandler(object state)
        {
            var vm = new AboutViewModel(new AboutView(), _updateChecker);
            vm.View.ShowDialog(this.View);
        }
        /// <summary>
        /// 
        /// </summary>
        private void CheckPendingFittingChanges()
        {
            if (SelectedFitting == null || !SelectedFitting.IsDirty) return;

            var vm = new ConfirmationViewModel(new ConfirmationView(), string.Format(Messages.message_save_fitting_pending_changes, SelectedFitting.Name)) { ButtonOkContent = Messages.label_save, ButtonCancelContent = Messages.label_dont_save };
            var result = vm.View.ShowDialog(this.View);
            if (result.HasValue && result.Value)
            {
                if (!Repository.Fittings.Contains(SelectedFitting))
                    Repository.Fittings.Add(SelectedFitting);

                Repository.SaveFittings(true);
            }
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="e"></param>
        private void ShowDownloadNewVersionConfirmation(NewVersionAvailableEventArgs e)
        {
            App.Trace.TraceInformation("New version available. Version:{0}", e.NewVersion);

            var vm = new ConfirmationViewModel(new ConfirmationView())
            {
                Title = "New version",
                ButtonOkContent = Messages.label_yes,
                ButtonCancelContent = Messages.label_no,
                ConfirmationMessage = String.Format("{0}\r\n\r\n{1}",
                                               String.Format(Messages.messsage_confirmation_new_version, e.NewVersion),
                                               e.Description),
                ShowButtonCancel = true
            };

            var result = vm.View.ShowDialog(View);
            if (result.HasValue && result.Value)
            {
                try
                {
                    Process.Start(e.DownloadLink);
                }
                catch (Exception exp)
                {
                    vm.ConfirmationMessage = String.Format("An exception of type {0} occured while attempting to go to {1}.\r\n\r\nDetails: {2}",
                                                           exp.GetType(),
                                                           e.DownloadLink,
                                                           exp.Message);
                    vm.ShowButtonCancel = false;
                    vm.ButtonOkContent = Messages.label_ok;
                    vm.View.Title = "Exception";
                    vm.View.ShowDialog(View);
                }
            }
        }
        /// <summary>
        /// Child view Closing event handler
        /// </summary>
        private void OnChildViewClosing(object sender, CancelEventArgs e)
        {
            var view = sender as IView;
            if (view == null) return;

            _children.Remove(view);
            view.Closing -= OnChildViewClosing;
        }
        /// <summary>
        /// Main view Closing event handler
        /// </summary>
        private void OnMainViewClosing(object sender, CancelEventArgs e)
        {
            if (_children != null)
                foreach (var child in _children.ToArray())
                    child.Close();

            // Auto save fitting changes
            if (Settings.Default.SaveFittingsOnExit &&
                SelectedFitting != null &&
                SelectedFitting.IsDirty)
            {
                if (!Repository.Fittings.Contains(SelectedFitting))
                    Repository.Fittings.Add(SelectedFitting);

                Repository.SaveFittings(false);
            }

            View.Closing -= OnMainViewClosing;
        }
        /// <summary>
        /// Clipboard explorer FittingStored event handler
        /// </summary>
        private void OnFittingDiscovered(object sender, FittingStoredEventArgs e)
        {
            if (e == null || 
                string.IsNullOrEmpty(e.Name) || 
                string.IsNullOrEmpty(e.RobotName)) return;

            var vm = new ConfirmationViewModel(new ConfirmationView())
            {
                ShowButtonCancel = true,
                ButtonOkContent = Messages.label_yes,
                ButtonCancelContent = Messages.label_cancel,
                ConfirmationMessage = string.Format(Messages.message_confirmation_import_fitting, e.Name, e.RobotName),
                Title = Messages.label_import_fitting,
            };

            var result = vm.View.ShowDialog(this.View);
            if (!result.HasValue || !result.Value) return;

            var fitting = e.Fitting;

            if (Repository.Fittings.Exists(fitting.Name))
            {
                int count = 1;
                fitting.Name = string.Format("{0} - {1}", fitting.Name, count);
                while (Repository.Fittings.Exists(fitting.Name))
                    fitting.Name = string.Format("{0} - {1}", fitting.Name, count++);
            }
            fitting.IsDirty = true;
            Fittings.Add(fitting);
        }
        /// <summary>
        /// Determines if a path represents the local path (e.g : ".")
        /// </summary>
        /// <param name="value">The path to verify</param>
        /// <returns>True if the path is the local path otherwise false</returns>
        private static bool IsLocalApplicationPath(string value)
        {
            return string.Equals(Path.GetFullPath(value), Path.GetFullPath("."));
        }
        /// <summary>
        /// Determines if the application can write and delete in a directory
        /// </summary>
        /// <param name="directory">The path to the directory to test</param>
        /// <returns>True if the application write and delete otherwise false</returns>
        private static bool CanWriteInDirectory(string directory)
        {
            if (string.IsNullOrEmpty(directory)) return false;

            bool success = false;
            try
            {
                using (var fs = File.Create(directory +  "\\test.tmp" ))
                    fs.Close();

                File.Delete(directory + "\\test.tmp" );
                success = true;
            }
            catch (Exception exp)
            {
                Trace.TraceError("An exception of type \"{0}\" occured while trying to create a file in the directory \"{2}\". Details: {1}", exp.GetType(), exp.Message, Path.GetFullPath(directory));
            }

            return success;
        }
    }
}